package com.zqc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zqc.entity.SysMenu;
import com.zqc.entity.SysRole;
import com.zqc.entity.SysUser;
import com.zqc.mapper.SysUserMapper;
import com.zqc.service.SysMenuService;
import com.zqc.service.SysRoleService;
import com.zqc.service.SysUserService;
import com.zqc.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zqc
 * @since 2023-03-07
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Autowired
    public SysRoleService roleService;

    @Autowired
    public SysUserMapper userMapper;

    @Autowired
    public SysMenuService menuService;

    @Autowired
    public RedisUtil redisUtil;

    @Autowired
    public SysUserService sysUserService;

    @Override
    public SysUser getUserByUsername(String username) {
        return getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
    }

    /**
     * 根据用户id获取用户权限（角色、菜单）
     *
     * @param userId
     * @return
     */
    @Override
    public String getUserAuthority(Long userId) {
        // 获取完成后格式：ROLE_admin,ROLE_test,sys:role:update
        String authorities = "";

        SysUser user = sysUserService.getById(userId);

        // 将用户权限进行缓存
        // 如果缓存中不存在用户权限信息，从数据库中查询
        if (!redisUtil.hasKey("GrantedAuthority" + user.getUsername())) {
            // 根据用户id查询用户角色
            List<SysRole> sysRoleList = roleService.list(new QueryWrapper<SysRole>()
                    .inSql("id", "select role_id from sys_user_role where user_id = " + userId));

            // 如果sysRoleList不为空，将sysRoleList里面的code保存到authorities中
            if (sysRoleList.size() > 0) {
                String roleNames = sysRoleList.stream().map(r -> "ROLE_" + r.getCode()).collect(Collectors.joining(","));
                authorities = roleNames.concat(",");
            }

            // 获取菜单
            // 根据用户id查询全部菜单id
            List<Long> menusIds = userMapper.getNavMenuIds(userId);
            if (menusIds.size() > 0) {
                // 通过菜单id查询菜单信息
                List<SysMenu> menus = menuService.listByIds(menusIds);
                String menuPerms = menus.stream().map(m -> m.getPerms()).collect(Collectors.joining(","));
                authorities = authorities.concat(menuPerms);
            }
            // 将权限信息存入redis中
            redisUtil.set("GrantedAuthority" + user.getUsername(), authorities, 60 * 60);
            System.out.println("用户权限信息从数据库中获取");
            return authorities;
        }
        // 如果缓存中有用户权限信息，直接从redis中获取
        authorities = (String) redisUtil.get("GrantedAuthority" + user.getUsername());
        System.out.println("用户权限信息从redis中获取");

        return authorities;
    }

    // 根据用户名清空 redis中用户权限
    @Override
    public void clearUserAuthorityInfoByUsername(String username) {
        redisUtil.del("GrantedAuthority" + username);
    }

    //    根据角色Id清空 redis中用户权限
    @Override
    public void clearUserAuthorityInfoByRoleId(Long roleId) {
        List<SysUser> users = this.list(new QueryWrapper<SysUser>()
                .inSql("id", "select user_id from sys_user_role where role_id = " + roleId));
        users.forEach(u -> {
            redisUtil.del("GrantedAuthority" + u.getUsername());
        });

    }

    // 根据菜单id清空 redis中用户权限
    @Override
    public void clearUserAuthorityInfoByMenuId(Long menuId) {
        List<SysUser> users = this.list(new QueryWrapper<SysUser>()
                .inSql("id", "select user_id from sys_role_menu rm join sys_user_role ur " +
                        "on rm.role_id = ur.role_id where rm.menu_id =" + menuId));
        users.forEach(u -> {
            redisUtil.del("GrantedAuthority" + u.getUsername());
        });
    }

}
